package cn.zwx.activiti.example.controller;

import cn.hutool.core.util.StrUtil;
import cn.zwx.activiti.example.common.ResponseEntry;
import cn.zwx.activiti.example.common.enums.ErrorEnum;
import cn.zwx.activiti.example.common.exception.BizException;
import cn.zwx.activiti.example.model.req.DeleteDefinitionReq;
import cn.zwx.activiti.example.model.req.ProcessDefinitionsForListReq;
import cn.zwx.activiti.example.model.req.ProcessDeploymentForListReq;
import cn.zwx.activiti.example.model.resp.ProcessDefinitionsForListResp;
import cn.zwx.activiti.example.model.resp.ProcessDeploymentForListResp;
import cn.zwx.activiti.example.model.resp.UploadStreamAndDeploymentResp;
import cn.zwx.activiti.example.service.ProcessDefinitionsService;
import cn.zwx.activiti.example.utils.SecurityUtil;
import cn.zwx.activiti.example.utils.ValidatorUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.engine.repository.Deployment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;


/**
 * @description:
 * @projectName:activiti-example
 * @see:cn.zwx.activiti.example.controller
 * @author:zhangwenxue
 * @createTime:2021/5/29 17:34
 * @version:1.0
 */
@Controller
@RequestMapping("process/definition")
@Api(tags = "工作流定义Api")
public class ProcessDefinitionsController extends BaseController {

    private Logger logger = LoggerFactory.getLogger(ProcessDefinitionsController.class);

    @Autowired
    private ProcessDefinitionsService processDefinitionsService;

    @Autowired
    private SecurityUtil securityUtil;



    /**
     * @description 查询可用的流程定义
     * @return cn.zwx.activiti.example.common.ResponseEntry
     * @author zhangwenxue
     * @createTime 2021/5/29 17:39
     **/
    @RequestMapping(value = "/list",method = RequestMethod.POST)
    @ApiOperation("查询可用的流程定义")
    @ResponseBody
    public ResponseEntry<Page<ProcessDefinitionsForListResp>> listForPage(@RequestBody ProcessDefinitionsForListReq req){
        // 校验参数
        securityUtil.logInAs(this.getUserName());
        ValidatorUtils.getInstance().validateEntity(req);
        // 请求接口
        Page<ProcessDefinitionsForListResp> page =  processDefinitionsService.listForPage(req);
        // 返回参数
        return ResponseEntry.ok(page);

    }
    /**
     * @description 查询流程部署列表
     * @return cn.zwx.activiti.example.common.ResponseEntry
     * @author zhangwenxue
     * @createTime 2021/5/29 17:39
     **/
    @RequestMapping(value = "/deployment/list",method = RequestMethod.POST)
    @ApiOperation("查询流程部署列表")
    @ResponseBody
    public ResponseEntry<Page<ProcessDeploymentForListResp>> deploymentList(@RequestBody ProcessDeploymentForListReq req){
        // 校验参数
        securityUtil.logInAs(this.getUserName());
        ValidatorUtils.getInstance().validateEntity(req);
        // 请求接口
        Page<ProcessDeploymentForListResp> page =  processDefinitionsService.deploymentList(req);
        // 返回参数
        return ResponseEntry.ok(page);

    }


    /**
     * @description 创建流程定义
     * @return cn.zwx.activiti.example.common.ResponseEntry
     * @author zhangwenxue
     * @createTime 2021/5/29 17:39
     **/
    @RequestMapping(value = "/create",method = RequestMethod.POST,headers = "content-type=multipart/form-data")
    @ApiOperation("创建流程定义")
    @ResponseBody
    public ResponseEntry uploadStreamAndDeployment(@RequestParam("processFile") MultipartFile processFile,String deploymentName) {
        // 校验参数
        securityUtil.logInAs(this.getUserName());
        if (Objects.isNull(processFile)){
            return ResponseEntry.defineError(new BizException(ErrorEnum.PARAMS_EMPTY_ERROR.getErrorCode(),"processFile参数不能为空"));
        }
        if (StrUtil.isBlank(deploymentName)){
            return ResponseEntry.defineError(new BizException(ErrorEnum.PARAMS_EMPTY_ERROR.getErrorCode(),"deploymentName参数不能为空"));
        }
        // 请求接口
        Deployment deployment = processDefinitionsService.create(processFile, deploymentName);
        // 返回参数
        UploadStreamAndDeploymentResp resp = new UploadStreamAndDeploymentResp();
        resp.setId(deployment.getId());
        resp.setKey(deployment.getKey());
        resp.setName(deployment.getName());
        deployment.getDeploymentTime();
        return ResponseEntry.ok(resp);
    }

    /**
     * @description 删除流程定义
     * @return cn.zwx.activiti.example.common.ResponseEntry
     * @author zhangwenxue
     * @createTime 2021/5/29 17:39
     **/
    @RequestMapping(value = "/delete",method = RequestMethod.POST)
    @ApiOperation("删除流程定义")
    @ResponseBody
    public ResponseEntry delete(@RequestBody DeleteDefinitionReq req) {
        // 校验参数
        securityUtil.logInAs(this.getUserName());
        ValidatorUtils.getInstance().validateEntity(req);
        // 请求接口
        processDefinitionsService.delete(req);
        // 返回参数
        return ResponseEntry.ok();
    }

    /**
     * @description 获取流程定义XML
     * @return void
     * @author zhangwenxue
     * @createTime 2021/5/30 0:14
     **/
    @ApiOperation("获取流程定义XML")
    @RequestMapping(value = "/getDefinitionXML",method = RequestMethod.GET)
    public void getProcessDefineXML(HttpServletResponse response,
                                    @RequestParam("definitionId") String definitionId) {
        // 校验参数
        securityUtil.logInAs(this.getUserName());
        if (StrUtil.isBlank(definitionId)){
           throw new BizException(ErrorEnum.PARAMS_EMPTY_ERROR.getErrorCode(),"definitionId参数不能为空");
        }
        try( InputStream inputStream = processDefinitionsService.getResourceAsStream(definitionId);
//             InputStream inputStream = repositoryService.getResourceAsStream(deploymentId,resourceName);
        ) {
            int count = inputStream.available();
            byte[] bytes = new byte[count];
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html");
            OutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }

        } catch (Exception e) {
            logger.error("获取流程定义XML异常",e);
            throw new BizException(ErrorEnum.GET_DEFINITION_XML_FAILED.getErrorCode(),ErrorEnum.GET_DEFINITION_XML_FAILED.getErrorMsg());
        }

    }

}
